package net.feling.mcloud.fragment;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import net.feling.mcloud.R.id;
import net.feling.mcloud.R.string;
import net.feling.mcloud.activity.MainActivity;
import net.feling.mcloud.entity.User;
import net.feling.mcloud.utils.Config;
import net.feling.mcloud.utils.HttpFetcher;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;

import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;

public class DistributeFragment implements LocationListener,
        OnCheckedChangeListener {

    private static final String TAG = "DistributeFragment";
    private boolean sendEnergy = true;
    private boolean begungps = false;

    private LocationManager locationManager;
    private static final int reflashInfoTime = 4 * 1000;
    private Context context;
    private View view;
    private EditText et_cpu, et_mem, et_battery, et_gate, et_gps, et_time, et_network_state, et_network_speed;
    private TextView tv_status;
    private Switch sw_gps;
    private Button bt_submit;
    private Intent batteryStatus;

    public static String GPSInfo = "";

    private OnClickListener listener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            if (bt_submit.getText().toString().equals(context.getResources()
                    .getString(string.distribute_bt_stop))) {
                sendEnergy = false;
                et_time.setEnabled(true);
                bt_submit.setText(context.getResources().getString(
                        string.distribute_bt_start));
                return;
            }
            if (checkInput()) {
                bt_submit.setText(context.getResources()
                        .getString(string.distribute_bt_stop));
                sendEnergy = true;
                savePreferences();
                et_time.setEnabled(false);
                long t = Long.parseLong(et_time.getText().toString()) * 1000;
                new sendEnergyTask(t).start();
            } else {
                tv_status.setText(context.getResources()
                        .getString(string.distribute_status_input_invalid));
            }
        }

    };

    public DistributeFragment(Context context, View view) {
        this.context = context;
        this.view = view;
    }

    /**
     * 使能UI控件
     */
    public void enable() {
        initView();
        restorePreferences();
        onCheckedChanged(null, sw_gps.isChecked());
        new reflashInfo().start();
    }

    /**
     * 初始化UI控件，设置按钮的点击事件监听
     */
    private void initView() {
        et_cpu = (EditText) view.findViewById(id.distribute_et_cpu);
        et_mem = (EditText) view.findViewById(id.distribute_et_mem);
        et_battery = (EditText) view.findViewById(id.distribute_et_battery);
        et_gate = (EditText) view.findViewById(id.distribute_et_gate);
        et_gps = (EditText) view.findViewById(id.distribute_et_gps);
        et_time = (EditText) view.findViewById(id.distribute_et_time);
        et_network_state = (EditText) view.findViewById(id.network_state);
        et_network_speed = (EditText) view.findViewById(id.network_speed);
        tv_status = (TextView) view.findViewById(id.distribute_tv_status);
        bt_submit = (Button) view.findViewById(id.distribute_bt_energy);
        bt_submit.setOnClickListener(listener);
        sw_gps = (Switch) view.findViewById(id.distribute_switch_gps);
        sw_gps.setOnCheckedChangeListener(this);
    }

    /**
     * 检查注册前，输入的合法性
     *
     * @return true/fasle
     */
    private boolean checkInput() {
        return et_time.getText().length() > 0 && Integer.parseInt(et_time.getText().toString()) > 3;
    }

    /**
     * 恢复之前保存的配置
     */
    private void restorePreferences() {
        SharedPreferences settings = context.getSharedPreferences(TAG, 0);
        String s_time = settings.getString("s_time", "600");
        boolean bool_gps = settings.getBoolean("bool_gps", false);
        et_time.setText(s_time);
        sw_gps.setChecked(bool_gps);
    }

    /**
     * 保存配置
     */
    private void savePreferences() {
        SharedPreferences settings = context.getSharedPreferences(TAG, 0);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString("s_time", et_time.getText().toString());
        editor.putBoolean("bool_gps", sw_gps.isChecked());
        editor.commit();
    }

    /**
     * 定时刷新设备(能量)信息
     */
    private class reflashInfo extends CountDownTimer {
        public reflashInfo() {
            super(reflashInfoTime, 1000);
            doReflashInfo();
        }

        public void onFinish() {
            doReflashInfo();
            new reflashInfo().start();
        }

        public void onTick(long millisUntilFinished) {
        }
    }

    private void doReflashInfo() {
        String cpufreq = getCPUFreq();
        String memleft = Config.getAvailMemory(context) + "";
        String batteryleft = getBatteryLeft();
        String gate = getGateid();
        String gps = getGPSInfo();
        String networkState = Config.isNetworkConnected(context) + "";
        int networkSpeed = Config.getNetSpeed();
        et_cpu.setText(cpufreq + " MHZ");
        et_mem.setText(memleft + " M");
        et_battery.setText(batteryleft + " %");
        et_gate.setText(gate);
        et_gps.setText(gps);
        et_network_state.setText(networkState);
        et_network_speed.setText(networkSpeed + "");
    }

    /**
     * 往代理发的设备(能量)信息, cpu频率|剩余内存|剩余电量|网关MAC|GPS信息
     *
     * @return
     */
    private String getInfo() {
        String cpufreq = et_cpu.getText().toString().replace(" MHZ", "");
        String memleft = et_mem.getText().toString().replace(" M", "");
        String batteryleft = et_battery.getText().toString().replace(" %", "");
        String gate = et_gate.getText().toString().replace("未获取到网关id", "None");
        String gps = et_gps.getText().toString().replaceAll(".+位置信息", "None");
        User user = new User();
        user.setUid(gate);
        user.setCPUfreq(cpufreq);
        user.setMemory(memleft);
        user.setBatteryLeft(batteryleft);
        user.setGPSInfo(gps);
        return cpufreq + "|" + memleft + "|" + batteryleft + "|" + gate + "|"
                + gps;
    }

    public User getUser() {
        String cpufreq = et_cpu.getText().toString().replace(" MHZ", "");
        String memleft = et_mem.getText().toString().replace(" M", "");
        String batteryleft = et_battery.getText().toString().replace(" %", "");
        String gate = et_gate.getText().toString().replace("未获取到网关id", "None");
        String gps = et_gps.getText().toString().replaceAll(".+位置信息", "None");
        User user = new User();
        user.setUid(gate);
        user.setCPUfreq(cpufreq);
        user.setMemory(memleft);
        user.setBatteryLeft(batteryleft);
        user.setGPSInfo(gps);
        return user;
    }

    /**
     * 获取cpu单核最大频率MHZ; 取不到返回1
     */
    private String getCPUFreq() {
        String result = "";
        ProcessBuilder cmd;
        try {
            String[] args = {"cat",
                    "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq"};
            cmd = new ProcessBuilder(args);
            Process process = cmd.start();
            InputStream in = process.getInputStream();
            byte[] re = new byte[24];
            while (in.read(re) != -1) {
                result = result + new String(re);
            }
            in.close();
        } catch (IOException ex) {
            ex.printStackTrace();
            result = "1024";
        }

        if (result.equals("")) {
            result = "1024";
        }
        return String.valueOf(Integer.parseInt(result.trim()) / 1024);
    }

    /**
     * 获取可用内存大小M
     */
    private String getMem() {
        String result = "";
        ProcessBuilder cmd;
        try {
            String[] args = {"cat",
                    "/proc/meminfo"};
            cmd = new ProcessBuilder(args);
            Process process = cmd.start();
            InputStream in = process.getInputStream();
            byte[] re = new byte[24];
            while (in.read(re) != -1) {
                result = result + new String(re);
            }
            in.close();
        } catch (IOException ex) {
            ex.printStackTrace();
            result = "1024";
        }
        if (result.equals("")) {
            result = "1024";
        }
        result = result.replaceAll("\n", "").replaceAll(".+MemFree:", "")
                .replaceAll("kB.+", "").trim();
        return String.valueOf(Integer.parseInt(result) / 1024);
    }

    /**
     * 获取剩余电量百分比
     */
    private String getBatteryLeft() {
        String result = "0";
        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        batteryStatus = context.registerReceiver(null, ifilter);
        int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        result = String.valueOf(level);
        if (result.equals("0")) {
            return "1";
        }
        return result;
    }

    /**
     * 网关MAC地址
     */
    private String getGateid() {
        String gateid = "";
        WifiManager wm = (WifiManager) context
                .getSystemService(Context.WIFI_SERVICE);
        if (wm.getConnectionInfo().getBSSID() == null ||
                "00:00:00:00:00:00".equals(wm.getConnectionInfo().getBSSID())) {
            gateid = "";
        } else {
            gateid = wm.getConnectionInfo().getBSSID();
        }
        if ("".equals(gateid)) {
            TelephonyManager tm = (TelephonyManager) context
                    .getSystemService(Context.TELEPHONY_SERVICE);
            GsmCellLocation location = (GsmCellLocation) tm.getCellLocation();
            int cellid = location.getCid();
            if (cellid != -1) {
                gateid = String.valueOf(cellid);
            }
        }
        if ("".equals(gateid)) {
            gateid = "未获取到网关id";
        }
        return gateid;
    }

    /**
     * 获取GPS信息 取不到返回 "None"
     */
    private String getGPSInfo() {
        if (GPSInfo.equals("")) {
            return "未获取到位置信息";
        }
        return GPSInfo;
    }

    private void initgps() {
        locationManager = (LocationManager) context
                .getSystemService(Context.LOCATION_SERVICE);

    }

    private void begingps() {
        DistributeFragment.GPSInfo = "";
        Criteria criteria = new Criteria();
        String provider = locationManager.getBestProvider(criteria, true);
        if (provider != null) {
            Log.i(TAG, "got " + provider + " provider");
            locationManager.requestLocationUpdates(provider, 4000, 2, this);
        }
    }

    private void endgps() {
        locationManager.removeUpdates(this);
        DistributeFragment.GPSInfo = "不获取位置信息";
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if (locationManager == null) {
            initgps();
        }
        if (isChecked) {
            begingps();
            begungps = true;
        } else {
            DistributeFragment.GPSInfo = "不获取位置信息";
            if (begungps) {
                endgps();
                begungps = false;
            }
        }
        savePreferences();
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            DistributeFragment.GPSInfo = String.valueOf(location.getLatitude())
                    + ","
                    + String.valueOf(location.getLongitude());
        }
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    @Override
    public void onProviderEnabled(String provider) {
        begingps();
        Log.i(TAG, provider + " enabled");
    }

    @Override
    public void onProviderDisabled(String provider) {
        endgps();
        Log.i(TAG, provider + " disabled");
    }

    /**
     * 每隔time秒，发送一个能量包
     */
    private class sendEnergyTask extends CountDownTimer {

        private Long time;

        public sendEnergyTask(Long time) {
            super(time, 1000);
            this.time = time;
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            try {
                nvps.add(new BasicNameValuePair("url", URLEncoder.encode(MainActivity.config
                        .getUrl("sendenergy"), "UTF-8")));
                nvps.add(new BasicNameValuePair("userid", URLEncoder
                        .encode(MainActivity.config.getUserid(), "UTF-8")));
                nvps.add(new BasicNameValuePair("info", URLEncoder
                        .encode(getInfo(), "UTF-8")));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            new doSendEnergy().execute(nvps);
        }

        public void onFinish() {
            if (sendEnergy) {
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                try {
                    nvps.add(new BasicNameValuePair("url", MainActivity.config
                            .getUrl("sendenergy")));
                    nvps.add(new BasicNameValuePair("userid", URLEncoder
                            .encode(MainActivity.config.getUserid(), "UTF-8")));
                    nvps.add(new BasicNameValuePair("info", URLEncoder
                            .encode(getInfo(), "UTF-8")));
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                new doSendEnergy().execute(nvps);
                new sendEnergyTask(time).start();
            }
        }

        public void onTick(long millisUntilFinished) {
        }
    }

    /**
     * 发送一次设备信息
     */
    private class doSendEnergy extends
            AsyncTask<List<NameValuePair>, Void, String> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            tv_status.setText(string.distribute_status_sending);
        }

        @Override
        protected String doInBackground(List<NameValuePair>... params) {
            String url = params[0].get(0).getValue();
            params[0].remove(0);

            /**
             * 这个地方需要改。
             */
             return new HttpFetcher().postString(url, params[0]);

        }

        @   Override
        protected void onPostExecute(String result) {
            bt_submit.setText(context.getResources().getString(
                    string.distribute_bt_stop));
            if (result == null) {
                tv_status.setText(string.distribute_status_send_fail_net);
                sendEnergy = false;
                bt_submit.setText(context.getResources().getString(
                        string.distribute_bt_start));
                et_time.setEnabled(true);
                return;
            }
            if (result.startsWith("<id>")) {
                tv_status.setText(string.distribute_status_send_success);

                if (!sendEnergy) {
                    tv_status.setText("");
                    bt_submit.setText(context.getResources().getString(
                            string.distribute_bt_start));
                    et_time.setEnabled(true);
                }
                return;
            }
            if (result.contains("Struts Problem Report")) {
                tv_status.setText(string.distribute_status_send_fail_strust);
                sendEnergy = false;
                bt_submit.setText(context.getResources().getString(
                        string.distribute_bt_start));
                et_time.setEnabled(true);
                return;
            }
            tv_status.setText(string.distribute_status_send_fail_other);
            sendEnergy = false;
            bt_submit.setText(context.getResources().getString(
                    string.distribute_bt_start));
            et_time.setEnabled(true);
        }
    }

}
